package me.chenqiang.tre.expression;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import me.chenqiang.tre.rule.Action;
import me.chenqiang.tre.rule.Rule;
import me.chenqiang.tre.rule.RuleChain;

public class ExpressionJson {
	protected ObjectMapper om = new ObjectMapper();	

	public ObjectNode dumpExpression(Expression expr) {
		ObjectNode exprNode = this.om.createObjectNode();
		exprNode.put("propertyName", expr.getPropertyName());
		exprNode.put("type", expr.getType());
		exprNode.put("propertyValue", expr.getPropertyValue());
		return exprNode;
	}

	public ObjectNode dumpAction(Action action) {
		ObjectNode actionNode = this.om.createObjectNode();
		actionNode.put("accept", action.isTransactionAccepted());
		if (action.getAdditionalChargeRate() != null) {
			actionNode.put("rate", action.getAdditionalChargeRate().toPlainString());
		}
		return actionNode;
	}

	public ObjectNode dumpRule(Rule rule) {
		ObjectNode ruleNode = this.om.createObjectNode();
		ArrayNode exprsNode = this.om.createArrayNode();
		for (Expression expr : rule.getExpressions()) {
			exprsNode.add(this.dumpExpression(expr));
		}
		ruleNode.set("expressions", exprsNode);
		ruleNode.set("action", this.dumpAction(rule.getAction()));
		return ruleNode;
	}

	public ObjectNode dumpRuleChain(RuleChain chain) {
		ObjectNode root = this.om.createObjectNode();
		ArrayNode rulesNode = this.om.createArrayNode();
		for (Rule rule : chain.getRules()) {
			rulesNode.add(this.dumpRule(rule));
		}
		root.set("rules", rulesNode);
		root.set("defaultAction", this.dumpAction(chain.getDefaultAction()));
		return root;
	}

	public String dumps(RuleChain chain) {
		ObjectNode root = this.dumpRuleChain(chain);
		ObjectWriter writer = this.om.writerWithDefaultPrettyPrinter();
		try {
			return writer.writeValueAsString(root);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
}
